﻿#include<iostream>
using namespace std;

//class Person//基类/父类
//{
//public:
//	// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证
//	void identity()
//	{
//		cout << "void identity()" << _name << endl;
//	}
//	void Print()
//	{
//		cout << _age << endl;
//	}
//
//protected://父类的保护成员可以在子类内被访问，但不能在类外被访问
//
//	string _name = "张三"; // 姓名
//
//private://父类的私有成员不能在子类内中直接被访问，可以被间接访问
//
//	int _age = 18; // 年龄
//};
//
//class Teacher : public Person//派生类/子类(公有继承)
//{
//public:
//	// 授课
//	void func()
//	{
//		Print();//间接访问父类的私有成员
//	}
//protected:
//	string title; // 职称
//};
//
////class Student : Person//class默认继承方式是private
////struct Student : Person//struct默认继承方式是public
//class Student : public Person//派生类/子类(公有继承)
////常用的继承方式是public，父类中成员常用访问限定符是protected
//{
//public:
//	// 学习
//	void study()
//	{
//		// ...
//	}
//protected:
//	int _stuid; // 学号
//};
//
//class A
//{
//public:
//	void fun()
//	{
//		cout << "func()" << endl;
//	}
//};
//class B : public A
//{
//public:
//	void fun(int i)
//	{
//		cout << "func(int i)" << i << endl;
//	}
//};
//
//int main()
//{
//	Student s;
//	s.identity();
//
//	//派生类的对象可以赋值给基类的指针和引用：切片(基类的指针/引用指向派生类中积累的那一部分)
//	Person* pp = &s;
//	Person& rp = s;
//
//	//基类的对象不可以赋值给派生类对象
//	Person p;
//	//s = p;//派生类比基类多出一部分，所以将基类赋值给派生类就会导致越界，会编译报错
//
//	Teacher t;
//	t.func();
//
//	//继承中的作用域：隐藏关系
//	//当父类和子类中含有同名成员时，子类会屏蔽父类对同名成员的直接访问，间接访问：基类名::成员名
//	B b;
//	b.fun(10);//调用派生类自己的成员函数
//	b.A::fun();//间接访问
//
//
//
//	return 0;
//}

//派生类的默认成员函数

//class Person
//{
//public:
//	//Person(const char* name = "peter")
//	Person(const char* name)
//		: _name(name)
//	{
//			cout << "Person()" << endl;
//	}
//
//	Person(const Person& p)
//		: _name(p._name)
//	{
//		cout << "Person(const Person& p)" << endl;
//	}
//
//	Person& operator=(const Person& p)
//	{
//		cout << "Person operator=(const Person& p)" << endl;
//		if (this != &p)
//			_name = p._name;
//		return *this;
//	}
//
//	~Person()
//	{
//		cout << "~Person()" << endl;
//	}
//protected:
//	string _name; // 姓名
//};
//
//// 子类中父类成员变量当成整体对象，作为子类自定义类型成员看待
//class Student : public Person
//{
//public:
//	// 报错
//	/*Student(const char* name, int num)
//		:_name(name)
//		,_num(num)
//	{}*/
//
//	Student(const char* name, int num)
//		:Person(name)//子类中父类成员变量当成整体对象，所以用匿名对象进行初始化
//		,_num(num)
//	{}
//
//	Student(const Student& s)
//		:Person(s)//派生类对象可以赋值给基类的指针和引用
//		,_num(s._num)
//	{
//		// 深拷贝 需要自己写，否则默认生成的就可以够了
//		//...
//	}
//
//	Student& operator=(const Student& s)
//	{
//		// 深拷贝 需要自己写，否则默认生成的就可以够了
//		if (this != &s)
//		{
//			Person::operator=(s);
//			_num = s._num;
//		}
//
//		return *this;
//	}
//
//	~Student()
//	{
//		// 不需要显示调用，保证析构时，先子后父
//		//Person::~Person();
//		delete[] _ptr;
//
//		// 派生类析构结束后，自动调用父类的析构
//	}
//protected:
//	int _num = 1; //学号
//
//	int* _ptr = new int[10];
//};


class A final//C++11出现的，加上这个关键字后就无法再被继承
{
public:
	void funa()
	{
		cout << "funa()" << endl;
	}
private:
	A()//通过语法限定，使派生无法调用基类的构造函数来实现无法继承：这种方法只有在实例化对象时才会报错，在不实例化对象时不会报错
	{}
};
//class B : public A
//{
//public:
//	void funb()
//	{
//		cout << "funb" << endl;
//	}
//};

//继承与友元的关系

//class Student;
//class Person
//{
//public:
//	friend void Display(const Person& p, const Student& s);
//	string _name; // 姓名
//	static int _count;//静态成员变量：类内声明，类外定义
//};
//
//int Person::_count = 1;//静态成员变量也是全局变量，就是受访问限定符限制，所以基类和派生类的静态成员变量是同一个
//
//class Student : public Person
//{
//public:
//	//父类的友元函数和子类没有关系，子类要想和这个函数构成友元就必须成为它的“朋友”:加friend
//	//“父亲的朋友不代表就是儿子的朋友”
//	friend void Display(const Person& p, const Student& s);
//
//protected:
//	int _stuNum; // 学号
//};
//
//void Display(const Person& p, const Student& s)
//{
//	cout << p._name << endl;
//	cout << s._stuNum << endl;
//}

//int main()
//{
//	//派生类的构造函数调用顺序是：先父后子
//	//派生类的析构函数调用顺序是：先子后父
//	/*Student s("李四",023);
//	Student s1 = s;*/
//
//	Student s;
//	Person p;
//	//Display(p, s);
//	
//	//非静态成员变量不是同一个
//	cout << &s._name << endl;
//	cout << &p._name << endl;
//
//	//静态成员变量是同一个
//	cout << &s._count << endl;
//	cout << &p._count << endl;
//	cout << &Student::_count << endl;
//	cout << &Person::_count << endl;
//
//	return 0;
//}

//多继承

class Person
{
public:
	string _name; // 姓名
};

class Student : virtual public Person//在菱形继承的情况时，就需要在腰处加上virtual
{
protected:
	int _num; //学号
};

class Teacher : virtual public Person
{
protected:
	int _id; // 职工编号
};

class Assistant : public Student, public Teacher
{
protected:
	string _majorCourse; // 主修课程
};

int main()
{
	// 编译报错：error C2385: 对“_name”的访问不明确
	Assistant a;
	a._name = "peter";

	// 需要显示指定访问哪个基类的成员可以解决二义性问题，但是数据冗余问题无法解决
	a.Student::_name = "xxx";
	a.Teacher::_name = "yyy";

	return 0;
}